﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Newtonsoft.Json;
using System.Net.Http;
using System.Threading.Tasks;

/// <summary>
/// 银联小程序支付工具类
/// </summary>
public class UnionPayHelper
{
    // 银联配置参数
    private readonly string _merId; // 商户号
    private readonly string _apiKey; // 商户API密钥
    private readonly string _unionPayUrl; // 银联支付接口地址
    private readonly string _notifyUrl; // 支付结果通知地址

    public UnionPayHelper(string merId, string apiKey, string unionPayUrl, string notifyUrl)
    {
        _merId = merId;
        _apiKey = apiKey;
        _unionPayUrl = unionPayUrl;
        _notifyUrl = notifyUrl;
    }

    /// <summary>
    /// 银联小程序下单
    /// </summary>
    /// <param name="orderNo">商户订单号</param>
    /// <param name="totalAmount">订单金额(元，保留两位小数)</param>
    /// <param name="subject">商品标题</param>
    /// <param name="openId">用户在银联小程序的标识</param>
    /// <returns>支付参数</returns>
    public async Task<UnionPayResponse> MiniProgramOrder(string orderNo, decimal totalAmount, string subject, string openId)
    {
        // 组装请求参数
        var parameters = new Dictionary<string, string>
        {
            {"service", "unified.trade.miniprogram.pay"},
            {"version", "1.0.0"},
            {"mer_id", _merId},
            {"out_trade_no", orderNo},
            {"total_amount", totalAmount.ToString("F2")},
            {"currency", "CNY"},
            {"subject", subject},
            {"client_ip", GetClientIp()},
            {"notify_url", _notifyUrl},
            {"timestamp", DateTime.Now.ToString("yyyyMMddHHmmss")},
            {"nonce_str", Guid.NewGuid().ToString("N")},
            {"open_id", openId} // 银联小程序用户标识
        };

        // 生成签名
        parameters.Add("sign", GenerateSign(parameters));

        // 发送请求
        var response = await PostFormData(_unionPayUrl, parameters);
        return JsonConvert.DeserializeObject<UnionPayResponse>(response);
    }

    /// <summary>
    /// 生成签名
    /// </summary>
    private string GenerateSign(Dictionary<string, string> parameters)
    {
        // 1. 排序参数
        var sortedParams = new SortedDictionary<string, string>(parameters);

        // 2. 拼接参数
        var sb = new StringBuilder();
        foreach (var param in sortedParams)
        {
            if (!string.IsNullOrEmpty(param.Value) && param.Key != "sign")
            {
                sb.Append($"{param.Key}={param.Value}&");
            }
        }

        // 3. 拼接API密钥并MD5加密
        sb.Append($"key={_apiKey}");
        using (var md5 = MD5.Create())
        {
            var bytes = Encoding.UTF8.GetBytes(sb.ToString());
            var hash = md5.ComputeHash(bytes);
            return BitConverter.ToString(hash).Replace("-", "").ToUpper();
        }
    }

    /// <summary>
    /// 发送表单请求
    /// </summary>
    private async Task<string> PostFormData(string url, Dictionary<string, string> data)
    {
        using (var httpClient = new HttpClient())
        {
            var content = new FormUrlEncodedContent(data);
            var response = await httpClient.PostAsync(url, content);
            return await response.Content.ReadAsStringAsync();
        }
    }

    /// <summary>
    /// 获取客户端IP
    /// </summary>
    private string GetClientIp()
    {
        // 实际项目中需根据环境获取真实IP
        return "127.0.0.1";
    }
}

/// <summary>
/// 银联支付响应实体
/// </summary>
public class UnionPayResponse
{
    public string code { get; set; } // 状态码：SUCCESS/FAIL
    public string msg { get; set; } // 提示信息
    public UnionPayResult result { get; set; }
}

public class UnionPayResult
{
    public string trade_no { get; set; } // 银联交易号
    public string out_trade_no { get; set; } // 商户订单号
    public string pay_info { get; set; } // 支付参数（需返回给小程序）
}
